"""ConfigMap资源提取器模块"""

from typing import Dict, Any, Optional, List
import yaml
import json
import logging
from src.extractors.base import Extractor

class ConfigMapExtractor(Extractor):
    """
    ConfigMap资源提取器
    负责从ConfigMap资源定义中提取关键信息
    """
    
    def __init__(self, logger: Optional[logging.Logger] = None):
        """初始化ConfigMap提取器"""
        super().__init__(logger)
        self.resource_type = "ConfigMap"
    
    def extract(self, content: str, file_path: str = "") -> Dict[str, Any]:
        """
        从ConfigMap YAML/JSON内容中提取信息
        
        Args:
            content: YAML/JSON格式的资源内容
            file_path: 资源文件路径，可选，用于日志记录
            
        Returns:
            提取的ConfigMap资源信息字典
        """
        # 解析YAML/JSON内容
        resource = self.parse_content(content, file_path)
        if not resource:
            return {}
            
        # 检查是否为ConfigMap资源
        if resource.get("kind") != "ConfigMap":
            self.logger.warning(f"资源不是ConfigMap: {file_path}")
            return {}
            
        # 提取基本信息
        result = self._extract_basic_info(resource)
        
        # 提取数据内容
        self._extract_data(resource, result)
        
        # 提取二进制数据
        self._extract_binary_data(resource, result)
        
        return result
    
    def _extract_basic_info(self, resource: Dict[str, Any]) -> Dict[str, Any]:
        """
        提取基本元数据信息
        
        Args:
            resource: 解析后的资源字典
            
        Returns:
            包含基本信息的字典
        """
        metadata = resource.get("metadata", {})
        
        result = {
            "kind": "ConfigMap",
            "name": metadata.get("name", ""),
            "namespace": metadata.get("namespace", "default"),
            "creation_timestamp": metadata.get("creationTimestamp", "")
        }
        
        # 提取标签和注解
        if "labels" in metadata:
            result["labels"] = metadata.get("labels", {})
            
        if "annotations" in metadata:
            result["annotations"] = metadata.get("annotations", {})
            
        return result
    
    def _extract_data(self, resource: Dict[str, Any], result: Dict[str, Any]) -> None:
        """
        提取ConfigMap数据内容
        
        Args:
            resource: 解析后的资源字典
            result: 要填充的结果字典
        """
        # 提取普通数据
        data = resource.get("data", {})
        if data:
            result["data"] = data
            
            # 尝试分析数据类型
            data_types = {}
            for key, value in data.items():
                data_type = self._detect_data_type(key, value)
                if data_type:
                    data_types[key] = data_type
            
            if data_types:
                result["data_types"] = data_types
    
    def _extract_binary_data(self, resource: Dict[str, Any], result: Dict[str, Any]) -> None:
        """
        提取ConfigMap二进制数据信息
        
        Args:
            resource: 解析后的资源字典
            result: 要填充的结果字典
        """
        binary_data = resource.get("binaryData", {})
        if binary_data:
            result["binary_data"] = binary_data
            
            # 分析二进制数据类型
            binary_types = {}
            for key, value in binary_data.items():
                binary_type = self._guess_binary_type(key)
                if binary_type:
                    binary_types[key] = binary_type
                    
            if binary_types:
                result["binary_data_types"] = binary_types
    
    def _detect_data_type(self, key: str, value: str) -> str:
        """
        检测配置数据的类型
        
        Args:
            key: 配置键名
            value: 配置内容
            
        Returns:
            数据类型字符串
        """
        # 尝试解析为JSON
        try:
            json.loads(value)
            return "json"
        except json.JSONDecodeError:
            pass
        
        # 尝试解析为YAML
        try:
            parsed = yaml.safe_load(value)
            if isinstance(parsed, (dict, list)) and parsed:  # 确保解析结果不是标量或空
                return "yaml"
        except yaml.YAMLError:
            pass
        
        # 尝试检测其他常见格式
        # XML
        if value.strip().startswith("<") and value.strip().endswith(">"):
            import re
            if re.search(r"<[^>]+>", value):
                return "xml"
        
        # 配置文件（key=value格式）
        if "\n" in value:
            lines = value.strip().split("\n")
            is_config = True
            for line in lines:
                line = line.strip()
                if line and not line.startswith("#") and "=" not in line:
                    is_config = False
                    break
            if is_config:
                return "properties"
        
        # 根据扩展名猜测
        if "." in key:
            ext = key.split(".")[-1].lower()
            if ext in ["json"]:
                return "json"
            elif ext in ["yaml", "yml"]:
                return "yaml"
            elif ext in ["xml"]:
                return "xml"
            elif ext in ["properties", "conf", "config", "env"]:
                return "properties"
            elif ext in ["sh", "bash"]:
                return "shell"
            elif ext in ["py"]:
                return "python"
            elif ext in ["js"]:
                return "javascript"
            elif ext in ["html", "htm"]:
                return "html"
            elif ext in ["css"]:
                return "css"
        
        # 默认为文本
        return "text"
    
    def _guess_binary_type(self, key: str) -> str:
        """
        根据键名猜测二进制数据类型
        
        Args:
            key: 二进制数据键名
            
        Returns:
            二进制数据类型字符串
        """
        if "." in key:
            ext = key.split(".")[-1].lower()
            
            # 图像文件
            if ext in ["jpg", "jpeg", "png", "gif", "bmp", "svg", "ico"]:
                return "image"
            
            # 文档文件
            if ext in ["pdf", "doc", "docx", "xls", "xlsx", "ppt", "pptx"]:
                return "document"
                
            # 压缩文件
            if ext in ["zip", "tar", "gz", "tgz", "rar", "7z"]:
                return "archive"
                
            # 证书和密钥
            if ext in ["crt", "pem", "key", "p12", "jks"]:
                return "certificate"
                
            # 二进制可执行文件
            if ext in ["exe", "dll", "so", "bin", "dat"]:
                return "binary"
        
        return "unknown"